package com.info.zhiduoduo.weixin.exceptionhandler;

import com.info.zhiduoduo.common.constants.SmartResult;
import com.info.zhiduoduo.common.constants.StatusMsg;
import com.info.zhiduoduo.common.exception.ApiException;
import com.info.zhiduoduo.common.exception.SmartException;
import com.info.zhiduoduo.common.utils.NumberUtil;
import com.info.zhiduoduo.core.service.DingdingNoticeService;

import org.apache.commons.collections4.CollectionUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.validation.BindException;
import org.springframework.validation.FieldError;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;

import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;

import javax.validation.ConstraintViolation;
import javax.validation.ConstraintViolationException;

import lombok.extern.slf4j.Slf4j;

@Slf4j
@RestControllerAdvice
public class GlobalExceptionHandler {

	@Autowired
	DingdingNoticeService dingdingNoticeService;
/*
	@ExceptionHandler(value = Exception.class)
	public SmartResult exceptionHandle(Exception e) throws Exception {
		SmartResult smartResult = new SmartResult();
		log.error("全局异常", e);
		if(e instanceof SmartException){
			return SmartResult.ofException((SmartException) e);
		}if (e instanceof MybatisPlusException) {
			//数据库报错
			smartResult.setStateMsg(StatusMsg.StatusMsg_103);
		} else if (e instanceof MultipartException || e instanceof FileUploadBase.FileSizeLimitExceededException) {
			//文件上传超过限制
			smartResult.setStateMsg(StatusMsg.StatusMsg_105);
		} else if (e instanceof RollbackException) {
			smartResult.setState(StatusMsg.StatusMsg_198.getState());
			smartResult.setMsg(e.getMessage());
		} else if (e instanceof MethodArgumentNotValidException) {
			FieldError fieldError = ((MethodArgumentNotValidException) e).getBindingResult().getFieldError();
			smartResult.setStateMsg(StatusMsg.StatusMsg_101);
			if (fieldError != null) {
				smartResult.setMsg(fieldError.getDefaultMessage());
			}
		} else if (e instanceof ConstraintViolationException) {
			StringBuilder sb = new StringBuilder();
			for (ConstraintViolation<?> cv : ((ConstraintViolationException) e).getConstraintViolations()) {
				sb.append(cv.getMessage()).append(";");
			}
			smartResult.setStateMsg(StatusMsg.StatusMsg_101);
			smartResult.setMsg(sb.toString());
		} else {
			smartResult.setStateMsg(StatusMsg.StatusMsg_198);
		}
		smartResult.setSystemerrormsg(ExceptionUtil.getErrorStackTrace(e));
		return smartResult;
	}*/

	@ExceptionHandler(value = ApiException.class)
	public SmartResult errorhandler(ApiException e) {
		Exception cause = (Exception) e.getCause();
		log.error("", e);
		// 返回给前端的报错信息
		String msg = e.getMessage();
		if (cause instanceof SmartException) {
			// 过滤掉一些state，比如登录的报错信息
//			if (!NumberUtil.intIn(e.getState(), StatusMsg.StatusMsg_137.state, StatusMsg.StatusMsg_138.state,
//					StatusMsg.StatusMsg_139.state)) {
//				// Hippo业务异常
//				dingdingNoticeService.sendMessage("", e.logMsg);
//			}
		} else {
			// 其他系统异常，比如springboot框架层异常或java RuntimeException。
			msg = handleOtherExceptions(cause);
			String logMsg = e.logMsg + "报错信息 : " + msg;
			dingdingNoticeService.sendExceptionMessage(logMsg, cause);
		}
		SmartResult smartResult = SmartResult.fail(e.getState(), msg);
		smartResult.setObject(e.getData());
		smartResult.setList(e.getList());
		return smartResult;
	}

	private String handleOtherExceptions(Exception e) {
		// 处理所有的请求参数异常信息
		if (e instanceof BindException) {
			List<FieldError> fieldErrors = ((BindException)e).getBindingResult().getFieldErrors();
			StringBuilder sb = new StringBuilder();
			if (CollectionUtils.isNotEmpty(fieldErrors)) {
				sb.append(fieldErrors.stream().map(FieldError::getDefaultMessage).collect(Collectors.joining(";")));
			}
			sb.append(". ");
			return sb.toString();
		} else if (e instanceof MethodArgumentNotValidException) {
			List<FieldError> fieldErrors = ((MethodArgumentNotValidException)e).getBindingResult().getFieldErrors();
			StringBuilder sb = new StringBuilder();
			if (CollectionUtils.isNotEmpty(fieldErrors)) {
				sb.append(fieldErrors.stream().map(FieldError::getDefaultMessage).collect(Collectors.joining(";")));
			}
			sb.append(". ");
			return sb.toString();
		} else if (e instanceof ConstraintViolationException) {
			Set<ConstraintViolation<?>> violationSet = ((ConstraintViolationException) e).getConstraintViolations();
			StringBuilder sb = new StringBuilder();
			if (CollectionUtils.isNotEmpty(violationSet)) {
				sb.append(violationSet.stream().map(ConstraintViolation::getMessage).collect(Collectors.joining(";")));
			}
			sb.append(". ");
			return sb.toString();
		} else {
			return e.getMessage();
		}
	}
}
